package com.glq1218.role.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.glq1218.domain.*;
import com.glq1218.permission.mapper.PermissionMapper;
import com.glq1218.role.bo.AddRoleBO;
import com.glq1218.role.bo.QueryRoleBO;
import com.glq1218.role.bo.RoleBO;
import com.glq1218.role.bo.UpdateRoleBO;
import com.glq1218.role.entity.Role;
import com.glq1218.role.mapper.RoleMapper;
import com.glq1218.role.service.RoleService;
import com.glq1218.util.BeanCopyUtils;
import com.glq1218.util.ServiceUtils;
import com.glq1218.util.SortUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author glq1218
 * @description 权限表(Role)表服务实现类
 * @since 2023/4/11 13:57
 */
@Service("roleService")
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
    private final PermissionMapper permissionMapper;

    @Override
    public PaginationResult<RoleBO> queryRoleList(PaginationParam paginationParam, SortParam sortParam, IntervalStr intervalStr, QueryRoleBO queryRoleBO) {
        // 处理时间间隔
        Interval interval = ServiceUtils.getInterval(intervalStr);
        Page<Role> rolePage = new PageDTO<>(paginationParam.getCurrent(), paginationParam.getPageSize());
        // 查询条件对象
        String sortSql = "";
        if (StringUtils.hasText(sortParam.getSortField())) {
            sortSql = SortUtils.getSortSql(sortParam);
        }
        LambdaQueryWrapper<Role> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .like(StringUtils.hasText(queryRoleBO.getName()), Role::getName, queryRoleBO.getName())
                .like(StringUtils.hasText(queryRoleBO.getDescription()), Role::getDescription, queryRoleBO.getDescription())
                .eq(Objects.nonNull(queryRoleBO.getStatus()), Role::getStatus, queryRoleBO.getStatus())
                .between(StringUtils.hasText(intervalStr.getUpdatedAtStart()) && StringUtils.hasText(intervalStr.getUpdatedAtEnd()),
                        Role::getUpdatedAt, interval.getUpdatedAtStart(), interval.getUpdatedAtEnd())
                .between(StringUtils.hasText(intervalStr.getCreatedAtStart()) && StringUtils.hasText(intervalStr.getCreatedAtEnd()),
                        Role::getCreatedAt, interval.getCreatedAtStart(), interval.getCreatedAtEnd())
                .last(StringUtils.hasText(sortParam.getSortField()) && StringUtils.hasText(sortParam.getSortOrder()), sortSql);
        // 分页查询
        page(rolePage, lambdaQueryWrapper);
        // 获取总数，如果总数为0，就直接返回
        long total = rolePage.getTotal();
        if (total == 0L) {
            return PaginationResult.<RoleBO>builder().total(0L).build();
        }
        IPage<RoleBO> convert = rolePage.convert(this::getRoleBO);
        List<RoleBO> roleBOList = convert.getRecords();
        if (queryRoleBO.getPermissionList() != null) {
            roleBOList = roleBOList.stream().filter(roleBO -> {
                for (Long roleId : queryRoleBO.getPermissionList()) {
                    for (RolePermission rolePermission : roleBO.getPermissionList()) {
                        if (roleId.equals(rolePermission.getPermissionId())) {
                            return true;
                        }
                    }
                }
                return false;
            }).toList();
            total = roleBOList.size();
        }
        return PaginationResult.<RoleBO>builder()
                .total(total)
                .records(roleBOList)
                .build();
    }

    @Override
    public List<RoleBO> queryAllRole() {
        List<Role> roleList = getBaseMapper().selectList(Wrappers.query());
        return BeanCopyUtils.copyBeanList(roleList, RoleBO.class);
    }

    @Override
    public RoleBO getRoleById(Serializable id) {
        Role role = getById(id);
        if (Objects.isNull(role)) {
            return null;
        }
        return getRoleBO(role);
    }

    @Override
    public String updateRole(UpdateRoleBO updateRoleBO) {
        Role role = BeanCopyUtils.copyBean(updateRoleBO, Role.class);
        List<Long> permissionList = updateRoleBO.getPermissionList();
        boolean isSuccess;
        // 先删除该用户对应的所有权限信息
        isSuccess = getBaseMapper().updateById(role) > 0 && getBaseMapper().deleteRolePermission(role.getId()) > 0;
        // 有角色信息的时候才进行添加用户角色信息的操作
        if (Objects.nonNull(permissionList) && permissionList.size() > 0) {
            // 查询权限对应的父权限id，和父权限对应的顶层菜单
            List<Long> pidList = permissionMapper.queryPidListByIds(permissionList);
            List<Long> topList = permissionMapper.queryPidListByIds(pidList);
            permissionList.addAll(pidList);
            permissionList.addAll(topList);
            // 再把新的用户角色对应信息插入到中间表中
            isSuccess = getBaseMapper().addRolePermission(role.getId(),
                    permissionList.stream().distinct().collect(Collectors.toList())) > 0;
        }
        if (isSuccess) {
            return "更新成功";
        }
        throw new RuntimeException("更新失败");
    }

    @Override
    public String addRole(AddRoleBO addRoleBO) {
        Role role = BeanCopyUtils.copyBean(addRoleBO, Role.class);
        boolean save = save(role);
        if (save) {
            return "添加成功";
        }
        throw new RuntimeException("添加失败");
    }

    private RoleBO getRoleBO(Role role) {
        RoleBO roleBO = BeanCopyUtils.copyBean(role, RoleBO.class);
        List<RolePermission> rolePermissionList = permissionMapper.queryPermissionListByRoleId(roleBO.getId());
        roleBO.setPermissionList(rolePermissionList);
        return roleBO;
    }
}
